package com.koron.css2;

import com.koron.css2.serviceManage.bean.*;
import com.koron.css2.serviceManage.service.ServerService;
import com.koron.css2.serviceManage.utils.CommonUtils;
import com.koron.css2.serviceManage.utils.JsonUtils;
import com.koron.css2.serviceManage.utils.PageDetailLog;
import com.koron.util.DBSourceUtils;
import com.koron.util.InitParam;
import com.koron.util.Tools;
import nl.bitwalker.useragentutils.UserAgent;
import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.ADOConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;


/**
 * 预览PDF文件的公共入口
 * 可支持的预览文件：PDF文件
 *
 * @author zengxiong
 * @date 2023/9/1
 */
@Controller
public class PreviewPdfAction {

    /**
     * 服务管理类
     */
    @Resource
    private ServerService serverService;

    /**
     * 日志
     */
    private static Logger logger = LoggerFactory.getLogger(PreviewPdfAction.class);

    /**
     * 用于存储查询过的服务配置信息，这里不放redis而是放本地内存，访问更快
     */
    private HashMap<String, TService> tServiceMap = new HashMap<>();

    /**
     * 用于存储所有接口的实例，在接口被调用一次之后，实例对象存储在这里，方便后续调用
     */
    private HashMap<String, PreviewPdfInterface> serverMap = new HashMap<>();

    /**
     * 002营收系统
     */
    private static final String CUR_SERVICE_002 = "002";

    /**
     * 003服务分析系统
     */
    private static final String CUR_SERVICE_003 = "003";

    /**
     * 请求头key: url
     */
    private final String URL = "url";


//    /**
//     * pdf下载
//     *
//     * @param json    请求的对象数据
//     * @param request 请求Servlet对象
//     * @return ResponseBean 返回结果
//     * @throws Exception
//     */
//    @ResponseBody
//    @RequestMapping(value = ("/exportPdf.api"), method = RequestMethod.GET)
//    public HttpEntity<?> service(@RequestParam(required = true, name = "json") String json, HttpServletRequest request) throws Exception {
//        RequestBean requestBean = JsonUtils.jsonToPojo(json, RequestBean.class);
//        // 数据有效性校验
//        if (requestBean == null || StringUtils.isBlank(requestBean.getBusicode()) || StringUtils.isBlank(requestBean.getSysType())) {
//            return new ResponseEntity<String>("请求的json格式不正确,或者参数为空", HttpStatus.OK);
//        }
//        // 获取用户信息(包括用户信息，用户可选水司信息，用户当前水司信息)
//        UserInfoBean userInfo = Tools.getLoginBean(requestBean.getToken());
//        if (userInfo == null) {
//            return new ResponseEntity<String>("当前登录信息失效，请重新登录后再操作。", HttpStatus.UNAUTHORIZED);
//        }
//        // 获取服务信息
//        TService tService = getInterfaceInfo(requestBean.getBusicode(), requestBean.getToken());
//        if (tService == null) {
//            return new ResponseEntity<String>(requestBean.getBusicode() + "服务不存在", HttpStatus.UNAUTHORIZED);
//        }
//        // 检查用户是否有该服务的权限
//        if (!checkRight(userInfo, tService, request.getHeader(URL), requestBean)) {
//            return new ResponseEntity<String>("您无当前操作的权限(" + requestBean.getBusicode() + ")", HttpStatus.UNAUTHORIZED);
//        }
//        HttpEntity<?> httpEntity = null;
//        ResponseBean responseBean = new ResponseBean();
//        // 执行服务
//        try {
//            String dbEnv = "_default";
//            if (CUR_SERVICE_002.equals(userInfo.getCurService())) {
//                // 主数据库
//                if (tService.getDbMaster() == 1) {
//                    dbEnv = DBSourceUtils.getDbEnv(userInfo.getCurWaterCode(), true);
//                } else if (tService.getDbMaster() == 2) {
//                    // 从数据库
//                    dbEnv = DBSourceUtils.getDbEnv(userInfo.getCurWaterCode(), false);
//                    logger.info("当前的数据源为从库：{}", dbEnv);
//                } else {
//                    // 为空则为主库
//                    dbEnv = DBSourceUtils.getDbEnv(userInfo.getCurWaterCode());
//                }
//            }
//            if (CUR_SERVICE_003.equals(userInfo.getCurService())) {
//                //TODO
//            }
//            if (dbEnv == null) {
//                throw new RuntimeException("水司编号为：" + userInfo.getCurWaterCode() + "的数据源注册失败！");
//            }
//            // 从缓存中获取服务实例
//            ExportPdfInterface serverInterface = serverMap.get(requestBean.getBusicode());
//            if (serverInterface == null) {
//                serverInterface = (ExportPdfInterface) Class.forName(tService.getClassName()).newInstance();
//                serverMap.put(requestBean.getBusicode(), serverInterface);
//            }
//            //根据不同的数据连接，通过业务实体对象，执行具体的服务信息
//            ExportPdfInterface finalServerInterface = serverInterface;
//            httpEntity = ADOConnection.runTask(dbEnv, (factory) -> {
//                HttpEntity<?> ret = finalServerInterface.exportPdf(factory, userInfo, requestBean);
//                if (ret == null) {
//                    factory.close(false);
//                    throw new RuntimeException("没有httpEntity返回！");
//                }
//                if (ret instanceof ResponseEntity<?>) {
//                    if (HttpStatus.OK.value() != ((ResponseEntity<?>) ret).getStatusCodeValue()) {
//                        factory.close(false);
//                        if (ret.getBody() instanceof MessageBean<?>) {
//                            throw new RuntimeException(((MessageBean<?>) ret.getBody()).getDescription());
//                        }
//                    }
//                }
//                return ret;
//            }, HttpEntity.class);
//            responseBean.setCode(Constant.MESSAGE_INT_SUCCESS);
//            responseBean.setDescription("pdf导出成功");
//        } catch (Exception e) {
//            logger.error("pdf导出失败", e);
//            responseBean.setCode(Constant.MESSAGE_INT_FAIL);
//            responseBean.setDescription("pdf导出失败");
//            httpEntity = new ResponseEntity<String>("pdf导出失败：" + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
//        }
//        RecordLog(request, responseBean, requestBean, userInfo);
//        return httpEntity;
//    }

    /**
     * pdf文件预览统一入口
     * @param json
     * @param request
     * @param response
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = ("/previewPdf.api"), method = RequestMethod.GET)
    public void service(@RequestParam(required = true, name = "json") String json, HttpServletRequest request, HttpServletResponse response) throws Exception {
        InputStream stream = null;
        ServletOutputStream out = null;
        try {
            RequestBean requestBean = JsonUtils.jsonToPojo(json, RequestBean.class);
            // 数据有效性校验
            if (requestBean == null || StringUtils.isBlank(requestBean.getBusicode()) || StringUtils.isBlank(requestBean.getSysType())) {
                throw new RuntimeException("请求的json格式不正确,或者参数为空！");
            }
            // 获取用户信息(包括用户信息，用户可选水司信息，用户当前水司信息)
            UserInfoBean userInfo = Tools.getLoginBean(requestBean.getToken());
            if (userInfo == null) {
                throw new RuntimeException("当前登录信息失效，请重新登录后再操作。");
            }
            // 获取服务信息
            TService tService = getInterfaceInfo(requestBean.getBusicode(), requestBean.getToken());
            if (tService == null) {
                throw new RuntimeException(requestBean.getBusicode() + "服务不存在！");
            }
            // 检查用户是否有该服务的权限
            if (!checkRight(userInfo, tService, request.getHeader(URL), requestBean)) {
                throw new RuntimeException("您无当前操作的权限(" + requestBean.getBusicode() + ")！");
            }

            String dbEnv = "_default";
            if (CUR_SERVICE_002.equals(userInfo.getCurService())) {
                // 主数据库
                if (tService.getDbMaster() == 1) {
                    dbEnv = DBSourceUtils.getDbEnv(userInfo.getCurWaterCode(), true);
                } else if (tService.getDbMaster() == 2) {
                    // 从数据库
                    dbEnv = DBSourceUtils.getDbEnv(userInfo.getCurWaterCode(), false);
                    logger.info("当前的数据源为从库：{}", dbEnv);
                } else {
                    // 为空则为主库
                    dbEnv = DBSourceUtils.getDbEnv(userInfo.getCurWaterCode());
                }
            }
            if (CUR_SERVICE_003.equals(userInfo.getCurService())) {
                //TODO
            }
            if (dbEnv == null) {
                throw new RuntimeException("水司编号为：" + userInfo.getCurWaterCode() + "的数据源注册失败！");
            }
            // 从缓存中获取服务实例
            PreviewPdfInterface serverInterface = serverMap.get(requestBean.getBusicode());
            if (serverInterface == null) {
                serverInterface = (PreviewPdfInterface) Class.forName(tService.getClassName()).newInstance();
                serverMap.put(requestBean.getBusicode(), serverInterface);
            }
            //根据不同的数据连接，通过业务实体对象，执行具体的服务信息
            PreviewPdfInterface finalServerInterface = serverInterface;
            byte[] bytes = ADOConnection.runTask(dbEnv, (factory) -> {
                byte[] ret = finalServerInterface.getPdfByte(factory, userInfo, requestBean);
                if (ret == null) {
                    factory.close(false);
                    throw new RuntimeException("没有byte[]返回！");
                }
                return ret;
            }, byte[].class);

            response.addHeader("content-type", "application/pdf");
            response.addHeader("Content-Disposition", "inline");
            response.addHeader("Content-Length", String.valueOf(bytes.length));

            out = response.getOutputStream();
            stream = new ByteArrayInputStream(bytes);
            byte buff[] = new byte[1024];
            int length = 0;
            while ((length = stream.read(buff)) > 0) {
                out.write(buff,0,length);
            }
            RecordLog(request, null, requestBean, userInfo);
        } catch (Exception e) {
            logger.error("pdf预览失败", e);
        } finally {
            try {
                if (stream != null) {
                    stream.close();
                }
                if (out != null) {
                    out.flush();
                    out.close();
                }
            } catch (IOException ioe) {
                logger.error("previewPdf流关闭失败：", ioe);
            }
        }
    }


    /**
     * 从本地内存读取服务配置，如果没有就从数据库读取
     *
     * @param busicode
     * @param token
     * @return
     */
    private TService getInterfaceInfo(String busicode, String token) {
        TService tService = tServiceMap.get(busicode);
        if (tService == null) {
            tService = ADOConnection.runTask("_default", serverService, "selectByServiceCode", TService.class,
                    busicode);
            if (!InitParam.isDev) {
                tServiceMap.put(busicode, tService);
            }
        }
        return tService;
    }

    /**
     * 检查用户权限
     *
     * @param userInfo
     * @param tService
     * @param url
     * @return
     */
    private boolean checkRight(UserInfoBean userInfo, TService tService, String url, RequestBean requestBean) {
        return true;
    }

    /**
     * 记录调用日志
     *
     * @param request
     * @param responseBean
     * @param requestBean
     * @param userInfo
     */
    private void RecordLog(HttpServletRequest request, ResponseBean responseBean, RequestBean requestBean, UserInfoBean userInfo) {
        try {
            RecordBean recordBean = new RecordBean();
            String ua = request.getHeader("User-Agent");
            UserAgent userAgent = UserAgent.parseUserAgentString(ua);
            String browser = userAgent.getBrowser().getName();
            recordBean.setBrowserType(browser);
            recordBean.setWaterGroup(userInfo.getCurWaterCode());
            if (StringUtils.isBlank(userInfo.getCurWaterCode())) {
                recordBean.setWaterGroup("运维平台");
            }
            recordBean.setComments("调用" + requestBean.getBusicode());
            recordBean.setIpAddr(CommonUtils.getIpAddress(request));
            if (!StringUtils.isBlank(request.getHeader(URL))) {
                recordBean.setPageAddr(request.getHeader(URL));
            } else {
                recordBean.setPageAddr("abc(请求头header中未传递url信息)");
            }
            recordBean.setCaller(userInfo.getUserInfo().getAcount());
            recordBean.setCreateName(userInfo.getUserInfo().getName());
            recordBean.setCreateTime(CommonUtils.getCurrentTime());
            recordBean.setServiceCode(requestBean.getBusicode());
            recordBean.setRequest(JsonUtils.objectToJson(requestBean));
            recordBean.setResponse(JsonUtils.objectToJson(responseBean));
            PageDetailLog.put(recordBean);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }
}
